package com.atlas.micro.trafico;

import java.io.*;

import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.rms.RecordStore;

/**
 * <p>Title: TraficoMadrid</p>
 *
 * <p>Description: Programa j2me para ver las cámaras de Tráfico de Madrid</p>
 *
 * <p>Copyright: Copyright (c) Antonio García Rodríguez 2005</p>
 *
 * <p>Company: </p>
 *
 * @author Antonio García Rodríguez
 * @version 1.0
 */
public class TraficoMovilManager {
    protected static long contadorTraficoGenerado = 0;    

    private int anchoPantalla;
    private int altoPantalla;
    private boolean imagenApaisada;
    private boolean pantallaCompleta;
    private boolean imagenProporcional;
    private Vector camarasVector;
    private Vector camarasFiltradas;
    
    /**
     * Contructor por defecto
     */
    public TraficoMovilManager() {
        init();
    }

       /**
        * Obtiene el listado de camaras recuperando de divanbinario.com
        * @return
        */
    private Vector getCamarasVector() {
        if(camarasVector==null){
            synchronized(this){
                if(camarasVector==null)
                    camarasVector = recuperarCamaras();
            }
            
        }
        if(camarasFiltradas!=null)
            return camarasFiltradas;
        else
            return camarasVector;       
    }

    public boolean camarasDisponibles() {
        if(camarasVector==null){
            synchronized(this){
                if(camarasVector==null)
                    camarasVector = recuperarCamaras();
            }            
        }
        if(camarasFiltradas!=null)
            return !camarasFiltradas.isEmpty();
        else
            return !camarasVector.isEmpty();       
    }
    
    private byte[] getDataFromUrl(String url) {
         byte[] data = null;

        //Conexion URL
        HttpConnection http = null;
        //Stream de lectura
        DataInputStream iStrm = null;


        try {
            //Abrimos conexión
            http = (HttpConnection) Connector.open(url);
            //Realizamos la petición
            http.setRequestMethod(HttpConnection.GET);
            //Comprobamos que la respuesta tiene código 200
            if (http.getResponseCode() == HttpConnection.HTTP_OK) {
                //Recuperamos el stream de lectura
                iStrm = http.openDataInputStream();
                //Recuperamos la longitud de la respuesta.
                int length = (int) http.getLength();

                //Comprobamos que sea >0, si el servidor nos ha envíado la longitud
                //de la respuesta, reservamos espacio en un array y leemos por completo
                if (length > 0) {
                    data = new byte[length];
                    addReadedBytes(length);
                    iStrm.readFully(data);
                } else //Si el servidor no nos ha envíado la longitud, leer byte a byte.
                if (length == -1) {
                    //ByteArray utilizado en caso de no conocer el tamaño real de la respuesta
                    ByteArrayOutputStream bStrm = null;
                    bStrm = new ByteArrayOutputStream();
                    int ch;
                    while ((ch = iStrm.read()) != -1) {
                        bStrm.write(ch);                        
                    }
                    data = bStrm.toByteArray();
                    if(data!=null)
                      addReadedBytes(data.length);
                    bStrm.close();
                }                
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {

            if (iStrm != null) {
                try {
                    iStrm.close();
                } catch (IOException ex) {
                }
            }
            if (http != null) {
                try {
                    http.close();
                } catch (IOException ex1) {
                }
            }
        }

        return data;
    }

   
    /**
     * init
     */
    private void init() {
        /** @todo Cargar la configuración de fichero */
        anchoPantalla = 0;
        altoPantalla = 0;
        imagenApaisada = false;
        pantallaCompleta = true;
        imagenProporcional = true;
        camarasVector = null;
    }

    /**
     * getCamara
     *
     * @return Image
     */
    public Image getCamara(int indiceCamara) {
        Vector camarasVectorAux = getCamarasVector();
        byte[] imgData = getCamara(((Camara)camarasVectorAux.elementAt(indiceCamara)).getIdCamara());
        Image imgCamara = null;
        if (imgData != null) {
            //Construimos la imagen
            if ( anchoPantalla>0 || altoPantalla >0) {
                imgCamara = resize(Image.createImage(imgData, 0,
                                                     imgData.length), anchoPantalla, altoPantalla, imagenApaisada, imagenProporcional);
            } else
                imgCamara = Image.createImage(imgData, 0,
                                              imgData.length);
        }

        return imgCamara;

    }
    /**
     * recupera la imagen de la web
     * @param camara String
     * @param formato String
     * @return byte[]
     */
    private byte[] getCamara(String url) {       
        //URL de la imagen en texto        
        byte[] imageData = getDataFromUrl(url);

        return imageData;
    }

    public static Image resize(Image image, int width, int height, boolean rotate, boolean proporcional) {
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        int thumbWidth = 0;
        int thumbHeight = 0;
        //Si hay que rotar la imagen intercambiamos ancho por alto
        if(rotate==false){
            thumbWidth = width;
            thumbHeight = height;
        }else{
            thumbWidth = height;
            thumbHeight = width;
        }
        //Proporcional dejando libre la altura;
        if(proporcional)
            thumbHeight = -1;

        if (thumbHeight == -1)
            thumbHeight = thumbWidth * sourceHeight / sourceWidth;
        else
          if (thumbWidth == -1)
                 thumbWidth = thumbHeight * sourceWidth / sourceHeight;

        Image thumb =  Image.createImage(thumbWidth, thumbHeight);

        Graphics g = thumb.getGraphics();

        for (int y = 0; y < thumbHeight; y++) {
            for (int x = 0; x < thumbWidth; x++) {

                int dx = x * sourceWidth / thumbWidth;
                int dy = y * sourceHeight / thumbHeight;
                g.setClip(x, y, 1, 1);
                g.drawImage(image, x - dx, y - dy,
                            Graphics.LEFT | Graphics.TOP);
            }
        }

        Image immutableThumb =null;
       if (rotate==false)
         immutableThumb= Image.createImage(thumb);
       else
          immutableThumb=immutableThumb.createImage(thumb,0,0,thumbWidth,thumbHeight, Sprite.TRANS_ROT90);

        return immutableThumb;
    }

    public void setAnchoPantalla(int anchoPantalla) {
        this.anchoPantalla = anchoPantalla;
    }

    public void setAltoPantalla(int altoPantalla) {
        this.altoPantalla = altoPantalla;
    }

    public void setImagenApaisada(boolean imagenApaisada) {
        this.imagenApaisada = imagenApaisada;
    }

    public void setPantallaCompleta(boolean pantallaCompleta) {
        this.pantallaCompleta = pantallaCompleta;
    }

    public void setImagenProporcional(boolean imagenProporcional) {
        this.imagenProporcional = imagenProporcional;
    }


    public int getAnchoPantalla() {
        return anchoPantalla;
    }

    public int getAltoPantalla() {
        return altoPantalla;
    }

    public boolean isImagenApaisada() {
        return imagenApaisada;
    }

    public boolean isPantallaCompleta() {
        return pantallaCompleta;
    }

    public boolean isImagenProporcional() {
        return imagenProporcional;
    }

    /**
     * Recupera el listado de camaras, parsea la respuesta e instancia un conjunto de cámaras.
     * @return
     */
    public Vector recuperarCamaras(){
        Vector listaCamaras = new Vector();
        try {
            //borrarBBDD();
            String cadena = new String(getDataFromUrl("http://www.divanbinario.com/apps/trafico/camaras.txt"));
            int indiceDesde = 0;
            //RecordStore db = RecordStore.openRecordStore("traficoDB", true);
            int indiceHasta = 0;
            while(indiceDesde<cadena.length() && indiceHasta > -1){
                indiceHasta = cadena.indexOf( "\n", indiceDesde);
                if(indiceHasta>0){
                   String registro = cadena.substring(indiceDesde,indiceHasta );
                   indiceDesde = indiceHasta+1;
                   //db.addRecord(registro.getBytes(), 0, registro.getBytes().length);
                   listaCamaras.addElement(Camara.parse(registro));
                }
                
            }                        
        } catch (Exception ex) {
            ex.printStackTrace();
        } 
        return listaCamaras;  
       
    }

 private void borrarBBDD() {
        try {
            RecordStore.deleteRecordStore("traficoDB");
        } catch (Exception ex) {
        }
    }

    public String[] obtenerNombreCamaras() {
            return obtenerNombreCamaras(getCamarasVector());
    }

    private String[] obtenerNombreCamaras(Vector vector) {
        String[] arrayNombres = null;
        if(vector!=null && vector.size()>0){
           arrayNombres = new String[vector.size()];
           Enumeration camaras = vector.elements();          
           Camara camara = null;
           int indice = 0;
           while(camaras.hasMoreElements()){
               camara = (Camara) camaras.nextElement();
               arrayNombres[indice++] = camara.getNombre();
           }           
        }else{
            arrayNombres = new String[]{"(camaras no disponibles)"};
        }
        
        return arrayNombres;
    }
    
    public boolean filtrarCamaras(String filtro){
        //Si no es nulo filtramos
        if(filtro!=null && camarasVector!=null){
            Enumeration enumeration = camarasVector.elements();
            camarasFiltradas = null;
            camarasFiltradas = new Vector();
            while(enumeration.hasMoreElements()){
                Camara camara = (Camara) enumeration.nextElement();
                if(camara.getNombre().toUpperCase().indexOf(filtro.toUpperCase())!=-1){
                    camarasFiltradas.addElement(camara);
                }
            }
        }else{
            camarasFiltradas=null;
        }
        if(camarasVector==null||(camarasFiltradas!=null && camarasFiltradas.isEmpty())||(camarasVector!=null && camarasVector.isEmpty()) ) {
          return false;  
        }
        return true;
    }
    
    public  void addReadedBytes(long bytes){
        contadorTraficoGenerado+=bytes;
    }
    public  long getReadedBytes(){
        return contadorTraficoGenerado;
    }
}
